﻿using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using LFSRecord2.Model.Undo;
using LFSRecord2.Structures;

namespace LFSRecord2.Model
{
    public class CompLayerPropertyString : CompLayerPropertyBase
    {
        public string DefaultValue { get; private set; }

        private string _currentValue = "";
        public string CurrentValue
        {
            get { return (string)_currentValue; }
            set
            {
                _currentValue = value;
                OnPropertyChanged("CurrentValue");
            }
        }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
        }

        public CompLayerPropertyString(CompLayerBase parentLayer, int propertyIndex, string propertyName, string defaultValue, LayerPropertyValueMeaning propertyValueMeaning)
        {
            //_keyFrames = new List<CustomKeyFrame>();
            //KeyFrames = new SortableObservableCollection<CustomKeyFrame>(_keyFrames);

            IsEditable = true;
            ParentLayer = parentLayer;
            PropertyIndex = propertyIndex;
            PropertyName = propertyName;
            PropertyValueType = LayerPropertyValueTypes.String;
            PropertyValueMeaning = propertyValueMeaning;
            DefaultValue = defaultValue;
            _currentValue = DefaultValue;
        }

        public override void HandleNewPropertyBinding(CompLayerPropertyBase prop)
        {
        }

        public override void RemoveCurrentValueListener()
        {
        }

        public override CustomKeyFrame SetKeyAtCurrentTime(int frame)
        {
            // Check if there isn't a key already
            CustomKeyFrame kf = GetKeyAtTime(frame);
            if (kf != null)
                return kf;

            //kf = SetKeyFrame(frame, (string)GetValueAtTime(frame));
            kf = SetKeyFrame(frame, _currentValue);
            if (!IsAnimated)
                IsAnimated = true;

            return kf;
        }

        public CustomStringKeyFrame SetKeyFrame(int frame, string newValue)
        {
            CustomStringKeyFrame kf = new CustomStringKeyFrame(frame, newValue);
            AddKeyFrame(kf);
            return kf;
        }

        public override void AddKeyFrame(CustomKeyFrame key)
        {
            AddKeyFrame(key, true);
        }
        public override void AddKeyFrame(CustomKeyFrame key, bool autoBezier)
        {
            CustomStringKeyFrame newKey = (CustomStringKeyFrame)key;
            newKey.ParentProperty = this;
            newKey.ParentLayer = ParentLayer;

            // Insert or append the new key to the array
            int index = 0;
            bool haveInserted = false;
            foreach (CustomKeyFrame kf in KeyFrames)
            {
                if (kf.FrameNum > newKey.FrameNum)
                {
                    //Debug.WriteLine("Inserting Key at index " + index);
                    KeyFrames.Insert(index, newKey);
                    haveInserted = true;
                    break;
                }
                index++;
            }

            if (!haveInserted)
            {
                //Debug.WriteLine("Appending Key at end - " + index);
                KeyFrames.Add(newKey);
            }
            if (newKey.IsSelected)
            {
                HasSelectedKeyFrames = true;
                IsSelected = true;
                ParentLayer.IsSelected = ParentLayer.HasSelectedProperties();
                if (ParentLayer.IsCollapsed)
                    ParentLayer.IsCollapsed = false;
            }
            if (!_isAnimated)
            {
                _isAnimated = true;
                OnPropertyChanged("IsAnimated");
            }
            RewriteKeyFrameIndices();
            SetHasPreFrames();
            SetHasPostFrames();
            SetHasCurrentFrame();
            IsEdited = true;

            // Add event listeners
            newKey.PropertyChanged += KeyFramePropertyChangedHandler;
        }

        public override void DeleteAllKeyframes()
        {
            KeyFrames.Clear();
            IsEdited = true;
        }

        public override object GetValueAtFrame(int frame)
        {
            if (KeyFrames.Count == 0)
                return CurrentValue;
            if (frame < KeyFrames[0].FrameNum)
                return "";

            CustomStringKeyFrame fromKey = null;

            foreach (CustomStringKeyFrame kf in KeyFrames)
            {
                if (frame < kf.FrameNum)
                {
                    break;
                }
                fromKey = kf;
            }

            if (fromKey == null)
                return "";
            return fromKey.Value;
        }

        public override CustomKeyFrame OnCurrentValueChange()
        {
            if (!IsAnimated)
            {
                IsEdited = true;
                return null;
            }

            // Insert or adjust keyframe (according to CurrentValues)
            CustomStringKeyFrame kf = (CustomStringKeyFrame)GetKeyAtTime(LfsRecordController.FrameIndex);
            if (kf == null)
            {
                kf = (CustomStringKeyFrame)SetKeyAtCurrentTime(LfsRecordController.FrameIndex);
                return kf;
            }
            else
            {
                kf.Value = CurrentValue;
                return null;
            }
        }

        public override bool SetCurrentValue(int frame)
        {
            string newValue = (string)GetValueAtFrame(frame);
            if (CurrentValue == newValue)
                return false;

            CurrentValue = newValue;
            return true;
        }

        public void KeyFramePropertyChangedHandler(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "Value" || e.PropertyName == "FrameNum" || e.PropertyName == "IsAnimated")
            {
                IsEdited = true;
            }
            else if (e.PropertyName == "IsSelected")
            {
                if (((CustomKeyFrame)sender).IsSelected)
                    HasSelectedKeyFrames = true;

                IsSelected = HasSelectedKeyFrames;
                ParentLayer.IsSelected = ParentLayer.HasSelectedProperties();
            }
        }

        public override PropertyDataBase DataStructure()
        {
            Debug.WriteLine("Creating String Property Datastructure");

            PropertyStringData propertyData = new PropertyStringData()
            {
                ParentLayerIndex = ParentLayer.LayerIndex,
                PropertyIndex = PropertyIndex,
                IsSelected = IsSelected,
                IsAnimated = IsAnimated,
                ValueLock = ValueLock,
                BindingPropertyIndex = BindingPropertyIndex,
                BoundPropertyIgnoreParent = BoundPropertyIgnoreParent,
                NumKeyFrames = KeyFrames.Count,
                KeyFrames = new KeyFrameDataBase[KeyFrames.Count],

                CurrentValue = CurrentValue
            };

            // Populate keyframes
            for (int a = 0; a < KeyFrames.Count; a++)
            {
                propertyData.KeyFrames[a] = KeyFrames[a].DataStructure();
            }

            return propertyData;
        }
    }
}
